from loguru import logger
from django.conf import settings
from django.shortcuts import render, get_object_or_404
from django.http import JsonResponse, Http404
from django.db.models import Prefetch, Count
from django.core.paginator import Paginator, EmptyPage

from .models import Film, FilmToPoster, ActorToFilm, FilmTag


def moves_list(request):
    """电影列表页视图"""
    # 优化查询 - 只获取必要字段
    film_query = Film.objects.filter(
        # is_hot=True,
        # rating__gte=4.0,
        # votes__gte=1000
    ).only(
        'id', 'num', 'title', 'year', 'rating', 'votes', 'cover_url'
    ).prefetch_related(
        Prefetch(
            'film_to_poster',
            queryset=FilmToPoster.objects.filter(type=2).only('poster'),
            to_attr='posters'
        )
    ).annotate(
        poster_count=Count('film_to_poster')
    ).order_by(
        '-rating', '-votes'
    ).all()

    # 为每个电影添加主海报URL
    for film in film_query:
        if film.posters:
            film.main_poster_url = film.posters[0].poster.url
        else:
            film.main_poster_url = film.cover_url or settings.DEFAULT_POSTER_URL
    paginator = Paginator(film_query, 18)
    page = request.GET.get('page', 1)
    try:
        films = paginator.page(page)
    except EmptyPage:
        films = paginator.page(paginator.num_pages)
    return render(request, 'moves/list.html', {
        'films': films,
        'count': len(film_query),
        'page_title': '电影列表'
    })


def moves_detail(request, pk):
    """电影详情页视图（无缓存优化版）"""
    # 获取电影详情（优化查询）
    film = get_object_or_404(
        Film.objects.select_related('countrycode').prefetch_related(
            Prefetch(
                'film_to_poster',
                queryset=FilmToPoster.objects.exclude(type=2).only('poster', 'type'),
                to_attr='all_posters'
            ),
            Prefetch(
                'tags',
                queryset=FilmTag.objects.only('value'),
                to_attr='film_tags'
            )
        ).only(
            'id', 'num', 'title', 'original_title', 'year', 'premiered',
            'rating', 'votes', 'runtime', 'mpaa', 'countrycode', 'plot',
            'cover_url', 'trailer_url', 'website_url'
        ),
        pk=pk
    )

    # 获取相关演员
    actors = ActorToFilm.objects.filter(
        film_id=pk
    ).select_related(
        'actor'
    ).only(
        'actor__id', 'actor__name', 'role', 'is_representative'
    ).order_by('role')[:10]  # 限制10个演员

    # 获取推荐电影（基于标签相似度和评分）
    rec_movies = None
    if film.film_tags:
        # 获取当前电影的标签ID
        tag_ids = [tag.id for tag in film.tags.all()]
        logger.debug('Tag IDs: {}'.format(tag_ids))

        # 查询相似电影
        rec_movies = Film.objects.filter(
            tags__id__in=tag_ids,
            # is_hot=True
        ).exclude(
            pk=pk  # 排除当前电影
        ).annotate(
            tag_count=Count('tags')
        ).prefetch_related(
            Prefetch(
                'film_to_poster',
                queryset=FilmToPoster.objects.filter(type=2).only('poster'),
                to_attr='posters'
            )
        ).order_by(
            '-tag_count', '-rating'
        )[:4]
        logger.debug('相识标签的电影>>> {}', rec_movies.query)
    if not rec_movies:
        # 如果没有标签，则使用备用推荐方案
        rec_movies = Film.objects.filter(
            rating__gte=4.0
        ).exclude(
            pk=pk
        ).order_by(
            '-rating'
        )[:4]

    logger.debug('recommend movies >>> {}', rec_movies)
    # 组织海报数据
    background_posters = []
    stage_posters = []
    other_posters = []

    for poster in film.all_posters:
        if poster.type == 1:  # 背景图
            background_posters.append(poster.poster.url)
        elif poster.type == 5:  # 剧照
            stage_posters.append(poster.poster.url)
        else:
            other_posters.append(poster.poster.url)

    # 确保至少有一个背景图
    if not background_posters and film.cover_url:
        background_posters.append(film.cover_url)

    return render(request, 'moves/detail.html', {
        'move': film,
        'rec_movies': rec_movies,
        'actors': actors,
        'background_posters': background_posters[:3],  # 最多3张背景图
        'stage_posters': stage_posters[:10],  # 最多10张剧照
        'page_title': film.title
    })


def hot_films_api(request):
    # 解析查询参数
    page = int(request.GET.get('page', 1))
    page_size = min(int(request.GET.get('page_size', 10)), 50)  # 限制最大50
    countrycode = request.GET.get('countrycode')
    mpaa = request.GET.get('mpaa')
    year = request.GET.get('year')
    mosaic = request.GET.get('mosaic')
    sort_by = request.GET.get('sort', 'rating')

    # 构建基础查询
    queryset = Film.objects.filter(
        is_hot=True,
        premiered__isnull=False,
        rating__gte=4.0,
        votes__gte=1000
    ).select_related('countrycode')

    # 应用过滤条件
    if countrycode:
        queryset = queryset.filter(countrycode__code=countrycode)

    if mpaa:
        queryset = queryset.filter(mpaa=mpaa)

    if year:
        queryset = queryset.filter(year=year)

    if mosaic:
        # 将字符串转换为布尔值
        mosaic_bool = mosaic.lower() == 'true'
        queryset = queryset.filter(mosaic=mosaic_bool)

    # 应用排序
    sort_mapping = {
        'rating': '-rating',
        'votes': '-votes',
        'premiered': '-premiered',
        'year': '-year',
        'default': '-rating'
    }
    order_by = sort_mapping.get(sort_by, sort_mapping['default'])
    queryset = queryset.order_by(order_by)

    # 预取海报数据（优化性能）
    poster_prefetch = Prefetch(
        'filmtoposter_set',
        queryset=FilmToPoster.objects.filter(type__in=[1, 2, 5]),
        to_attr='posters'
    )
    queryset = queryset.prefetch_related(poster_prefetch)

    # 分页处理
    total_count = queryset.count()
    start_index = (page - 1) * page_size
    end_index = start_index + page_size
    films = queryset[start_index:end_index]

    # 手动序列化数据
    film_list = []
    for film in films:
        # 获取不同类型海报
        main_poster = next((p for p in film.posters if p.type == 2), None)
        background_poster = next((p for p in film.posters if p.type == 1), None)
        stage_posters = [p for p in film.posters if p.type == 5][:5]  # 最多5张剧照

        film_list.append({
            'num': film.num,
            'title': film.title,
            'original_title': film.original_title,
            'year': film.year,
            'premiered': film.premiered.strftime('%Y-%m-%d') if film.premiered else None,
            'rating': film.rating,
            'votes': film.votes,
            'runtime': film.runtime,
            'mpaa': film.mpaa,
            'country': film.countrycode.name if film.countrycode else None,
            'country_code': film.countrycode.code if film.countrycode else None,
            'mosaic': film.mosaic,
            'cover_url': main_poster.poster.url if main_poster else None,
            'background_url': background_poster.poster.url if background_poster else None,
            'stage_posters': [p.poster.url for p in stage_posters],
            'tags': [tag.name for tag in film.tags.all()][:3]  # 最多3个标签
        })

    # 构建响应数据
    response_data = {
        'code': 200,
        'message': 'success',
        'data': {
            'page': page,
            'page_size': page_size,
            'total': total_count,
            'has_more': end_index < total_count,
            'films': film_list
        }
    }
    return JsonResponse(response_data)


def get_actor_works(request, actor_id):
    # 使用预加载优化查询
    actor_work_films = ActorToFilm.objects.filter(
        actor_id=actor_id, is_representative=True
    ).prefetch_related(
        Prefetch(
            'film',
            queryset=Film.objects.prefetch_related(
                'tags'
            )
        )
    ).all()
    logger.debug('查询演员代表作>>>{}', actor_work_films.query)

    # 没有电影
    if not actor_work_films:
        return JsonResponse({})
    # 批量处理作品数据
    works_data = []
    for film in actor_work_films:
        film = film.film
        works_data.append({
            'num': film.id,
            'title': film.title,
            'year': film.year,
            'rating': film.rating,
            'country': film.countrycode.country if film.countrycode else None,
            'tags': [tag.value for tag in film.tags.all()]
        })
    logger.debug('代表作>>>{}', works_data)

    all_works = sorted(works_data, key=lambda x: x['year'], reverse=True)

    result = {
        'all_works': all_works,
    }
    return JsonResponse(result)


def get_actor_films(request, pk):
    # 直接获取所需字段值
    films_data = ActorToFilm.objects.filter(
        actor_id=pk
    ).select_related('film').values(
        'film__id',
        'film__num',
        'film__title',
        'film__year',
        'film__rating',
    ).order_by('-film__rating')
    # 检查演员是否存在
    if not films_data.exists():
        raise Http404("演员不存在或没有参演电影")

    # 单独获取标签
    film_ids = [item['film__id'] for item in films_data]
    tags_map = {}
    for film in Film.objects.filter(id__in=film_ids).prefetch_related('tags'):
        tags_map[film.id] = [tag.value for tag in film.tags.all()]
    # 获取每部电影的海报
    poster_map = {}
    for film in FilmToPoster.objects.filter(
            film_id__in=film_ids, type=3).all():
        poster_map[film.film_id] = film.poster.url
    # 组装数据
    films = []
    for item in films_data:
        films.append({
            'id': item['film__id'],
            'num': item['film__num'],
            'title': item['film__title'],
            'year': item['film__year'],
            'rating': item['film__rating'],
            'tags': tags_map.get(item['film__id'], []),
            'poster': poster_map.get(item['film__id'])
        })
    actor = ActorToFilm.objects.select_related('actor').filter(actor_id=pk).first()

    return render(request, 'moves/list.html', {
        'films': films,
        'count': len(films),
        'page_title': actor.actor.name,
    })
